#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         Install.py
#
# Copyright:    Copyright (c) 2004, Faulkner Technologies
#
# Author:       Brian Oliver
#
# Description:  This file defines the install() method to configure
#               the Knowledge Engine for use in a CMF Site.  It's meant
#               to be used as an External Method.
#
# ZMI Usage:    In the ZMI (Zope Management Interface)
#
#               1. Add an 'External Method' object to the root of the
#               'CMF/Plone Site' in which you wish to use 
#               KnowledgeEngines.
#
#               2. When creating the 'External Method', set it's 
#               properties to be:
#
#               id = 'KnowledgeEngineInstaller'
#               title = 'Prepares a CMF Site for use with a Knowledge Engine'
#               module name = 'KnowledgeEngine.Install'
#               function name = 'install'
#
#               3. After creation, go to the management screen of
#               the 'KnowledgeEngineInstaller' and select the 'Test'
#               tab.  This will execute the install function and
#               configure the CMF/Plone Site instance for use by
#               Knowledge Engine instances., including; 
#               i). registering appropriate content types,
#               ii). registering skins for all skinnable components.
#####################################################################

__doc__ = """Install script to setup the KnowledgeEngine in a CMF Site Instance"""

#####################################################################
## KnowledgeEngine Library Imports
from Products.KnowledgeEngine import KnowledgeEngineGlobals, getRegisteredClassInfo

#####################################################################
## Python Library Imports
from cStringIO import StringIO
import string
import os

#####################################################################
## Core Zope Imports
from OFS.Folder import Folder
from App.FindHomes import ppath
from zExceptions import BadRequest

#####################################################################
## CMF Library Imports
from Products.CMFCore.TypesTool import FactoryTypeInformation
from Products.CMFCore.DirectoryView import addDirectoryViews, createDirectoryView
from Products.CMFCore.utils import getToolByName


def install_configlet(self, out):
    """
        Installs a configlet for KnowledgeEngine to enable global properties
        such as permissions to be defined.
    """
    
    try:
        portal_conf=getToolByName(self,'portal_controlpanel')
    except AttributeError:
        print >>out, "Configlet could not be installed"
        return

    try:
        portal_conf.registerConfiglet(
            'KnowledgeEngine Configuration Tool',
            "Faulkner KnowledgeEngine",
            'string:${portal_url}/knowledgeengine_tool/permissions',
            '',
            'Manage portal',
            'Products',
            1,
            'KnowledgeEngine',
            'kupuimages/kupu_icon.gif',  # TODO: Change This!
            'KnowledgeEngine Tool',
            None,
        )
    except KeyError:
        pass # Get KeyError when registering duplicate configlet.


def install(self):
    """
        Configures a CMF Site for use with a Knowledge Engine
    """

    #buffer all output (so we can write it to the client AND the stdout on the server)
    out = StringIO()
    out.write("\n[KnowledgeEngine] Commence: Installing Knowledge Engine for use in the Zope CMF\n")

    ######################################
    ### STEP 1: Install the Knowledge Engine skins ###    
    
    #get the special folder (SkinsTool) called 'portal_skins' where the skins are located
    lSkinsTool = getToolByName(self, 'portal_skins')
    
    ##attempt to create a KnowledgeEngine file system directory view of the 
    ##KnowledgeEngine Cache (it contains all of the skins)
    if 'KnowledgeEngine' not in lSkinsTool.objectIds():
        #create a directory view
        try:
            createDirectoryView(lSkinsTool, 'lib/python/Products/KnowledgeEngine/Cache', 'KnowledgeEngine')
        except ValueError:
            createDirectoryView(lSkinsTool, 'KnowledgeEngine/Cache', 'KnowledgeEngine')
                
        out.write("[KnowledgeEngine] Created 'KnowledgeEngine' directory view layer in the 'portal_skins'\n")
    else:
        out.write("[KnowledgeEngine] Skipping layer creation: 'KnowledgeEngine' directory view already exists in the 'portal_skins'\n")


    ######################################
    ### STEP 2: Register the 'KnowledgeEngine' skin folder with the 'portal_skin' Tool ###    
    
    #attempt to add the 'KnowledgeEngine' skin to each of the skin selections
    for lSkin in lSkinsTool.getSkinSelections():
    
        #get the skins path for the current skin
        lPath = lSkinsTool.getSkinPath(lSkin)
        
        #split the path (it is comma separated) so we can add a new path (to the KnowledgeEngine)
        lPath = map(string.strip, string.split(lPath,','))
        
        #ensure the KnowledgeEngine skin isn't already in the path for the current skin
        if 'KnowledgeEngine' not in lPath:
            #attempt to insert into the path after the custom skins folder 
            #(this allows the KnowledgeEngine skins to be customised but after that, the KnowledgeEngine skins take priority)
            try: 
                lPath.insert(lPath.index('custom') + 1, 'KnowledgeEngine')
            except ValueError:
                #prepend as we want the KnowledgeEngine to be first in the list if we can't add after the 'custom' skin
                lPath = ['KnowledgeEngine'] + lPath
                
            #add the necessary comma (to separate paths)                
            lPath = string.join(lPath, ', ')
            
            #re-add the skin path (updates the object so the skin path is saved)
            lSkinsTool.addSkinSelection(lSkin, lPath)
            
            out.write("[KnowledgeEngine] Added 'KnowledgeEngine' to path in skin '%s'\n" % lSkin)
            
        else:
            out.write("[KnowledgeEngine] Skipping skin '%s'. KnowledgeEngine is already in the skin path\n" % lSkin)

    ######################################
    ### STEP 3: Register the Environment as a 'portal_type' ###    

    #get the types tool (we need to register the Environment in here)
    lTypesTool = getToolByName(self, 'portal_types')
    
    #TODO: Make this generic to use the registered portal object types!!!
    #attempt to install the type (it may fail as it is already in the portal_types)    
    #try:

    def addTypeInfo( add_meta_type, id, typeinfo_name, **kw ):
        try:
            lTypesTool.manage_addTypeInformation( add_meta_type=add_meta_type, id=id, typeinfo_name=typeinfo_name, **kw )
        except BadRequest: # The tool already exists
            out.write("[KnowledgeEngine] %s already in portal types\n" % id)
        
        

    addTypeInfo(add_meta_type='Factory-based Type Information', id='MyKnowledgePortlet', typeinfo_name='KnowledgeEngine: MyKnowledgePortlet (MyKnowledgePortlet)')
    out.write("[KnowledgeEngine] Added 'MyKnowledgePortlet' to the 'portal_types'\n")

    addTypeInfo(add_meta_type='Factory-based Type Information', id='MySQLTableEntitySource', 
                typeinfo_name='KnowledgeEngine: MySQLTableEntitySource (MySQLTableEntitySource)')
    out.write("[KnowledgeEngine] Added 'MySQLTableEntitySource' to the 'portal_types'\n")

    addTypeInfo(add_meta_type='Factory-based Type Information', id='ModelEntitySource', typeinfo_name='KnowledgeEngine: ModelEntitySource (ModelEntitySource)')
    out.write("[KnowledgeEngine] Added 'ModelEntitySource' to the 'portal_types'\n")

    addTypeInfo(add_meta_type='Factory-based Type Information', id='CountryEntitySource', typeinfo_name='KnowledgeEngine: CountryEntitySource (CountryEntitySource)')
    out.write("[KnowledgeEngine] Added 'CountryEntitySource' to the 'portal_types'\n")

    addTypeInfo(add_meta_type='Factory-based Type Information', id='Model', typeinfo_name='KnowledgeEngine: Model (Model)')
    out.write("[KnowledgeEngine] Added 'Model' to the 'portal_types'\n")
        
    #except:
    #    out.write("[KnowledgeEngine] Skipping type 'Model'.  Already registered in the 'portal_types'\n")

    # Install configlet
    install_configlet(self, out)
    out.write("[KnowledgeEngine] Configlet installed\n")

    out.write("[KnowledgeEngine] Complete: Installed Knowledge Engine for use in the Zope CMF\n")
    
    #output the stdout
    print out.getvalue()
    
    #return the outcome to be rendered on the client browser
    return out.getvalue()



def uninstall(self):
    """
        Remove various bits of KE from the plone portal.
        
        TODO: This needs to include the CMF types etc in future.
    """
    out = StringIO()
    
    # Remove the configlet
    configTool = getToolByName(self, 'portal_controlpanel', None)
    if configTool:
        configTool.unregisterConfiglet('KnowledgeEngine Configuration Tool')
        out.write('Removed KnowledgeEngine configlet\n')
    
    print >> out, "Successfully uninstalled KnowledgeEngine."
    return out.getvalue()
    